home *** CD-ROM | disk | FTP | other *** search
- /*
- * (c)Copyright 1992-1997 Obvious Implementations Corp. Redistribution and
- * use is allowed under the terms of the DICE-LICENSE FILE,
- * DICE-LICENSE.TXT.
- */
-
- /*
- * STMT.C
- *
- * Parse procedural junk: declarations, statements, etc...
- */
-
- /*
- ** $Filename: stmt.c $
- ** $Author: dice $
- ** $Revision: 30.152 $
- ** $Date: 1995/01/08 22:30:25 $
- ** $Log: stmt.c,v $
- * Revision 30.152 1995/01/08 22:30:25 dice
- * test message
- *
- * Revision 30.5 1994/06/13 18:37:37 dice
- * .
- *
- * Revision 30.0 1994/06/10 18:04:57 dice
- * .
- *
- * Revision 1.8 1994/04/15 21:18:54 jtoebes
- * Handle labels before the start of a case clause properly.
- *
- * Revision 1.7 1993/10/17 04:03:38 jtoebes
- * Eliminate compiler warning about unused variable.
- *
- * Revision 1.6 1993/10/15 22:44:24 jtoebes
- * Eliminated old code which called cerror.
- *
- * Revision 1.5 1993/09/19 13:14:10 jtoebes
- * Fixed BUG00148 - Compiler does not catch gotos to non-existent label.
- * Changed intermediate gotolabel information to know more about the label.
- * Also added code to identify when more than one label has been entered.
- *
- * Revision 1.4 1993/09/11 16:12:41 jtoebes
- * Fixed BUG01010 - Code not allowed in switch statement before the first case.
- * Added code to catch the code before the first case statement and store it
- * to be emitted later.
- *
- * Revision 1.3 1993/09/06 22:18:01 jtoebes
- * Fixed BUG06004 - DC1 fails to detect reuse of a register in a function parameter
- * list.
- *
- **/
-
- #include "defs.h"
-
- Prototype short CompProcedureArgDeclarators(short, Var ***, long *, long *);
- Prototype short CompProcedure(short, Var *);
- Prototype short CompStmtDeclExp(short, Stmt **, long);
- Prototype short CompBlock(short, Stmt **);
- Prototype short CompFor(short, Stmt **);
- Prototype short CompWhile(short, Stmt **);
- Prototype short CompDo(short, Stmt **);
- Prototype short CompIf(short, Stmt **);
- Prototype short CompSwitch(short, Stmt **);
- Prototype short CompBreak(short, Stmt **);
- Prototype short CompContinue(short, Stmt **);
- Prototype short CompGoto(short, Stmt **);
- Prototype short CompLabel(short, Stmt **);
- Prototype short CompReturn(short, Stmt **);
- Prototype short CompBreakPoint(short, Stmt **);
-
- /*
- * Deals with argument declarations to a procedure. Does NOT compile
- * the procedure itself.
- *
- * Determines registerization, if any, for both externs and procedure
- * definitions.
- *
- * void foo ( {START} a, b, c, d ) <more>
- * void foo ( {START} short, short) <more>
- * void foo ( {START} short a, short b) <more>
- *
- * more = old style declarators (which I like much better than proto style anyway),
- * optional .. could be ';' if just a prototype. If a procedure
- * definition then returns TokSemi.
- */
-
- short
- CompProcedureArgDeclarators(short t, Var ***pvars, long *pargs, long *pflags)
- {
- Var **vars = NULL;
- short i;
- short n = -1;
- short siz = 0;
- short oldState = State;
-
- State = SARG;
-
- *pargs = 0;
- *pvars = NULL;
- *pflags = 0;
-
- if (t == TokDotDotDot) {
- *pflags |= TF_DOTDOTDOT | TF_PROTOTYPE;
- t = GetToken();
- if (t != TokRParen)
- zerror(EERROR_SYNTAX_ERROR_DECL);
- n = 0;
- }
-
- while (t != TokRParen) {
- Type *baseType;
- Type *type;
- Var *var;
- Symbol *sym = NULL;
- long baseFlags;
- long regFlags;
-
- if (n < 0)
- n = 0;
-
- /*
- * If not an ID we assume it is a type declaration and thus this
- * is a prototype.
- */
-
- if (t != TokId && t != TokVarId && t != TokEnumConst)
- *pflags |= TF_PROTOTYPE;
-
- t = CompType(t, &baseType, &baseFlags, ®Flags); /* defaults to int if none */
- type = baseType;
- t = CompTypeDeclarators(t, &type, &sym, baseFlags);
- if (regFlags & RF_REGISTER)
- {
- int i;
-
- *pflags |= TF_REGCALL;
- /* Ensure that the register is not used by any other parameter */
- for(i = 0; i < n; i++)
- {
- if (vars[i]->RegFlags == regFlags)
- {
- zerror(EERROR_ILLEGAL_REGSPEC);
- regFlags = 0;
- }
- }
- }
-
- if (type == &VoidType) {
- if (n)
- zerror(EERROR_SYNTAX_ERROR_DECL);
- if (t != TokRParen)
- zerror(EERROR_SYNTAX_ERROR_DECL);
- break;
- }
-
- if (n == siz) {
- siz += 4;
- vars = zrealloc(vars, sizeof(Var *), n, siz);
- }
-
- /*
- * argument
- */
-
- var = AllocStructure(Var);
- var->Type = type;
- var->Sym = sym;
- var->Flags = (baseFlags & TF_STORQUALMASK) | type->Flags | (VF_ARG | TF_AUTO);
- var->RegFlags = regFlags;
-
- if (type->Id != TID_INT && type->Id != TID_PTR && type->Id != TID_ARY)
- *pflags |= TF_STKCALL;
-
- if (baseFlags & (TF_STATIC|TF_EXTERN))
- zerror(EERROR_ILLEGAL_QUALIFIER);
-
- /*
- * Bump the refs for the 'register' keyword to give the variable
- * a better chance of being put in a register.
- */
-
- if (var->Flags & TF_REGISTER)
- ++var->Refs;
-
- vars[n++] = var;
-
- if (t != TokRParen && t != TokComma) {
- zerror(EERROR_SYNTAX_ERROR_DECL);
- goto bad;
- }
- if (t == TokComma) {
- t = GetToken();
- if (t == TokDotDotDot) {
- *pflags |= TF_DOTDOTDOT;
- t = GetToken();
- if (t != TokRParen)
- zerror(EERROR_SYNTAX_ERROR_DECL);
- }
- }
- }
- *pargs = n;
- *pvars = vars;
-
- /*
- * have right paren, now is this a real procedure or just a declaration
- * of some sort?
- */
-
- t = GetToken();
-
- if (t == TokComma || t == TokEq || t == TokSemi || t == TokRParen) {
- if (!(*pflags & TF_PROTOTYPE))
- *pflags |= TF_STKCALL;
- goto skip;
- }
-
- /*
- * Else a real procedure.. handle old-style argument decls. We return
- * when we get a '{'. Also make sure all the variables are named.
- */
-
- for (i = 0; i < n; ++i) {
- Var *var = vars[i];
-
- if (var->Sym == NULL) {
- zerror(EERROR_ID_MISSING_PROC);
- var->Sym = MakeSymbol("____dummy", 9, TokId, 0);
- /* goto bad; */
- /* break; */
- }
- }
-
- while (t != TokLBrace) {
- Type *baseType;
- Type *type;
- Var *var = NULL;
- Symbol *sym = NULL; /* XXX needed? */
- long baseFlags;
- long regFlags;
- long li = LFBase->lf_Index;
-
- t = CompType(t, &baseType, &baseFlags, ®Flags); /* defaults to int if none */
-
- for (;;) {
- type = baseType;
- t = CompTypeDeclarators(t, &type, &sym, baseFlags);
-
- for (i = 0; i < n; ++i) {
- var = vars[i];
- if (var->Sym == sym)
- break;
- }
- if (i == n) {
- zerror(EERROR_ID_NOT_IN_LIST);
- } else {
- var->Type = type;
- var->Flags = (baseFlags & TF_STORQUALMASK) | type->Flags | (VF_ARG | TF_AUTO);
- var->RegFlags = regFlags;
- if (var->Flags & TF_REGISTER)
- ++var->Refs;
- if (regFlags & RF_REGISTER)
- *pflags |= TF_REGCALL;
- }
- if (type->Id != TID_INT && type->Id != TID_PTR && type->Id != TID_ARY)
- *pflags |= TF_STKCALL;
-
- if (t == TokComma) {
- t = GetToken();
- continue;
- }
- break;
- }
- if (t != TokSemi) {
- zerror(EERROR_EXPECTED_SEMICOLON);
- if (li == LFBase->lf_Index) /* prevent inifinite loop */
- t = GetToken();
- break;
- }
- t = GetToken();
- }
-
- skip:
-
- /*
- * If explicitly registerized then clear TF_STKCALL bit (which gets
- * set when automatic registerization is not possible)
- */
-
- if (*pflags & TF_REGCALL)
- *pflags &= ~TF_STKCALL;
-
- bad:
- State = oldState;
- return(t);
- }
-
- /*
- * Compiles a procedure, t had better be TokLBrace.
- *
- * returns TokSemi to simply toplevel.c
- *
- * Normally assigns in decls work as follows: the variable is added to the
- * current block's variable list and the decl-stmt is added to the current
- * block's statement list (which retains placement).
- */
-
- short
- CompProcedure(short t, Var *var)
- {
- Stmt *stmt;
- short oldState = State;
- long lexIdx = LFBase->lf_Index;
-
- if (t != TokLBrace)
- zerror(EERROR_EXPECTED_OCBRACE_PROC);
-
- State = SARG; /* first properly add args */
- var->u.Block = BlockDown(BT_PROC);
-
- {
- short i;
- Type *type = var->Type;
-
- for (i = 0; i < type->Args; ++i) {
- Var *xvar = type->Vars[i];
-
- BlockAddVar(xvar);
- Assert(xvar->Sym);
- SemanticAdd(xvar->Sym, TokVarId, xvar);
- }
- }
-
- State = SINSIDE;
- t = CompBlock(GetToken(), &stmt);
- BlockAddStmt(stmt);
-
- State = SARG;
- BlockUp();
- State = SOUTSIDE;
-
- /*
- * t should be TokRBrace.. return TokSemi instead
- */
-
- if (t != TokRBrace)
- yerror(lexIdx, EERROR_EXPECTED_OCBRACE_PROC);
-
- State = oldState;
- return(TokSemi);
- }
-
- short
- CompStmtDeclExp(short t, Stmt **pstmt, long semiexp)
- {
- *pstmt = NULL;
-
- switch(t) {
- case TokLBrace:
- t = CompBlock(GetToken(), pstmt);
- t = GetToken();
- break;
- case TokBreak:
- t = CompBreak(GetToken(), pstmt);
- break;
- case TokCase:
- zerror(EERROR_CASE_DEFAULT_OUTSIDE);
- t = GetToken();
- break;
- case TokContinue:
- t = CompContinue(GetToken(), pstmt);
- break;
- case TokDefault:
- zerror(EERROR_CASE_DEFAULT_OUTSIDE);
- t = GetToken();
- break;
- case TokDo:
- BlockCost += 2;
- t = CompDo(GetToken(), pstmt);
- BlockCost -= 2;
- break;
- case TokElse:
- zerror(EERROR_ELSE_NO_IF);
- t = GetToken();
- break;
- case TokFor:
- BlockCost += 2;
- t = CompFor(GetToken(), pstmt);
- BlockCost -= 2;
- break;
- case TokGoto:
- t = CompGoto(GetToken(), pstmt);
- break;
- case TokIf:
- t = CompIf(GetToken(), pstmt);
- break;
- case TokReturn:
- t = CompReturn(GetToken(), pstmt);
- break;
- case TokSwitch:
- t = CompSwitch(GetToken(), pstmt);
- break;
- case TokWhile:
- BlockCost += 2;
- t = CompWhile(GetToken(), pstmt);
- BlockCost -= 2;
- break;
- case TokBreakPoint:
- t = CompBreakPoint(GetToken(), pstmt);
- break;
- case TokSemi:
- if (semiexp)
- t = GetToken();
- break;
-
- /*
- * declaration
- */
-
- case TokStruct:
- case TokEnum:
- case TokUnion:
- case TokTypeQual:
- case TokTypeDef:
- case TokTypeId:
- case TokTypeof:
- {
- Var *var = NULL;
- BlockStmt *block = NULL;
-
- t = CompDecl(t, &var, semiexp);
-
- /*
- * add variables to the current block, any procedure decls
- * will be moved to the top level. Returns base of list
- * of newly added variables to the current block (minus any
- * procdures added to the top)
- */
-
- if (var)
- var = BlockAddVar(var);
-
- if (var && var->Next) /* more 'n one! */
- block = BlockDown(BT_BLOCK);
-
- while (var) { /* for each... */
- if (var->Type->Id != TID_PROC && var->u.AssExp && (var->Flags & TF_AUTO)) {
- ExpStmt *es = AllocTmpStructure(ExpStmt);
-
- es->st_Func = (void (*)(void *))GenExp;
- es->st_Tok = TokExp;
- es->st_LexIdx = LFBase->lf_Index;
- InsertAssign(&var->u.AssExp, var);
- es->Expr = var->u.AssExp;
- ++var->Refs;
- if (block)
- BlockAddStmt((Stmt *)es);
- else
- *pstmt = (Stmt *)es;
- }
- var = var->Next;
- }
- if (block) {
- *pstmt = (Stmt *)block;
- BlockUp();
- }
- }
- break;
- case TokLabelId:
- Assert(0);
- /* t = CompLabel(t, pstmt); */
- break;
- case TokId: /* label or subroutine call ? */
- case TokVarId: /* label or variable ? */
- if (LexHackColon) { /* label (lexical hack checks for a :) */
- t = CompLabel(t, pstmt);
- break;
- }
- /* fall through to exp */
- default:
-
- {
- Exp *exp = NULL;
- ExpStmt *es = AllocTmpStructure(ExpStmt);
- long li = LFBase->lf_Index;
-
- t = CompExp(t, &exp, 1);
- if (semiexp) {
- if (t == TokSemi) {
- t = GetToken();
- } else {
- zerror(EWARN_EXPECTED_SEMICOLON);
- if (LFBase->lf_Index == li) /* prevent endless loop */
- t = GetToken();
- }
- }
- if (exp == NULL)
- zerror(EFATAL_SYNTAX_ERROR_EXP);
-
- es->st_Func = (void (*)(void *))GenExp;
- es->st_Tok = TokExp;
- es->st_LexIdx = exp->ex_LexIdx;
- es->Expr = exp;
- *pstmt = (Stmt *)es;
- }
- break;
- }
- return(t);
- }
-
- /*
- * CompBlock() works slightly differently in that it returns t = TokRBrace,
- * allowing toplevel.c to simply throw away t (makes the code easier)
- *
- * All Comp*() for statements have access to their parent blocks... they
- * need not set it (it's done automatically on return) UNLESS they make
- * calls to other Comp*() statements.
- *
- * Attempt to set block->LastLexIdx for debug info synchronization to just
- * before the close brace. This does not always work perfectly (but does
- * not cause a screwup in those cases either).
- */
-
- short
- CompBlock(short t, Stmt **pstmt)
- {
- BlockStmt *block = BlockDown(BT_BLOCK);
-
- *pstmt = (Stmt *)block;
-
- while (t != TokRBrace) {
- Stmt *stmt;
-
- t = CompStmtDeclExp(t, &stmt, 1);
- BlockAddStmt(stmt);
- if (!t)
- break;
- }
- BlockUp();
-
- return(t);
- }
-
- /*
- * for (stmt ; exp; stmt) stmt
- *
- * Note: The Block junk is to add another variable level allowing
- * temporary declarations within the for.. for (int i = 0; ...)
- */
-
- short
- CompFor(short t, Stmt **pstmt)
- {
- ForStmt *stmt = AllocTmpStructure(ForStmt);
- BlockStmt *block = BlockDown(BT_FOR);
-
- *pstmt = (Stmt *)block;
- stmt->Block = block;
- block->LabelLoop = AllocLabel();
- block->LabelTest = AllocLabel();
- block->LabelBreak = AllocLabel();
-
-
- BlockAddStmt((Stmt *)stmt);
-
- stmt->st_Func = (void (*)(void *))GenFor;
- stmt->st_Tok = TokFor;
- stmt->st_LexIdx = LFBase->lf_Index;
- stmt->LabelBegin = AllocLabel();
-
- t = SkipToken(t, TokLParen);
-
- if (t != TokSemi)
- t = CompStmtDeclExp(t, &stmt->Stmt1, 0);
- t = SkipToken(t, TokSemi);
- if (t != TokSemi)
- t = CompStmtDeclExp(t, &stmt->Stmt2, 0);
- t = SkipToken(t, TokSemi);
- if (t != TokRParen)
- t = CompStmtDeclExp(t, &stmt->Stmt3, 0);
- t = SkipToken(t, TokRParen);
- t = CompStmtDeclExp(t, &stmt->Stmt4, 1);
-
- if (stmt->Stmt2) {
- if (stmt->Stmt2->st_Tok != TokExp)
- zerror(EFATAL_STMT_COND_NOT_EXP);
-
- InsertBranch(&((ExpStmt *)stmt->Stmt2)->Expr, COND_T, block->LabelLoop);
- }
-
- BlockUp();
-
- return(t);
- }
-
- short
- CompWhile(short t, Stmt **pstmt)
- {
- WhileStmt *stmt = AllocTmpStructure(WhileStmt);
- BlockStmt *block = BlockDown(BT_WHILE);
-
- *pstmt = (Stmt *)block;
- stmt->Block = block;
- block->LabelLoop = AllocLabel();
- block->LabelTest = AllocLabel();
- block->LabelBreak = AllocLabel();
-
- BlockAddStmt((Stmt *)stmt);
-
- stmt->st_Func = (void (*)(void *))GenWhile;
- stmt->st_Tok = TokWhile;
- stmt->st_LexIdx = LFBase->lf_Index;
-
- t = SkipToken(t, TokLParen);
-
- t = CompStmtDeclExp(t, &stmt->Stmt1, 0);
- t = SkipToken(t, TokRParen);
- t = CompStmtDeclExp(t, &stmt->Stmt2, 1);
-
- if (stmt->Stmt1->st_Tok != TokExp)
- zerror(EFATAL_STMT_COND_NOT_EXP);
- InsertBranch(&((ExpStmt *)stmt->Stmt1)->Expr, COND_T, block->LabelLoop);
-
- BlockUp();
-
- return(t);
- }
-
- short
- CompDo(short t, Stmt **pstmt)
- {
- DoStmt *stmt = AllocTmpStructure(DoStmt);
- BlockStmt *block = BlockDown(BT_DO);
-
- *pstmt = (Stmt *)block;
- stmt->Block = block;
- block->LabelLoop = AllocLabel();
- block->LabelTest = AllocLabel();
- block->LabelBreak = AllocLabel();
-
- BlockAddStmt((Stmt *)stmt);
-
- stmt->st_Func = (void (*)(void *))GenDo;
- stmt->st_Tok = TokDo;
- stmt->st_LexIdx = LFBase->lf_Index;
-
- t = CompStmtDeclExp(t, &stmt->Stmt1, 1); /* code */
- t = SkipToken(t, TokWhile);
- t = CompStmtDeclExp(t, &stmt->Stmt2, 1); /* test */
-
- if (stmt->Stmt2->st_Tok != TokExp)
- zerror(EFATAL_STMT_COND_NOT_EXP);
- InsertBranch(&((ExpStmt *)stmt->Stmt2)->Expr, COND_T, block->LabelLoop);
-
- BlockUp();
-
- return(t);
- }
-
- short
- CompIf(short t, Stmt **pstmt)
- {
- IfStmt *stmt = AllocTmpStructure(IfStmt);
-
- *pstmt = (Stmt *)stmt;
- stmt->st_Func = (void (*)(void *))GenIf;
- stmt->st_Tok = TokIf;
- stmt->st_LexIdx = LFBase->lf_Index;
-
- stmt->LabelIf = AllocLabel();
- stmt->LabelElse = AllocLabel();
- stmt->LabelEnd = AllocLabel();
-
- t = SkipToken(t, TokLParen);
- t = CompStmtDeclExp(t, &stmt->Stmt1, 0); /* cond */
- /* Make sure that the expression actually returns a value */
-
- t = SkipToken(t, TokRParen);
- t = CompStmtDeclExp(t, &stmt->StmtT, 1); /* true */
- if (t == TokElse)
- t = CompStmtDeclExp(GetToken(), &stmt->StmtF, 1); /* false */
-
- if (stmt->Stmt1->st_Tok != TokExp)
- zerror(EFATAL_STMT_COND_NOT_EXP);
- InsertBranch(&((ExpStmt *)stmt->Stmt1)->Expr, COND_F, stmt->LabelElse);
-
- return(t);
- }
-
- /*
- * switch (exp) { ... }
- *
- * Not only is exp in a semantic level, but each case/default is as well, so
- * you can: case 1:
- * int i = 4;
- * ...
- * case 2:
- * int i = 5;
- * ...
- *
- */
-
- short
- CompSwitch(short t, Stmt **pstmt)
- {
- SwitchStmt *stmt = AllocTmpStructure(SwitchStmt);
- BlockStmt *block = BlockDown(BT_SWITCH);
- short siz = 0;
- short haveCase = 0;
-
- *pstmt = (Stmt *)block;
-
- BlockAddStmt((Stmt *)stmt);
-
- stmt->st_Func = (void (*)(void *))GenSwitch;
- stmt->st_Tok = TokSwitch;
- stmt->st_LexIdx = LFBase->lf_Index;
-
- stmt->Block = block;
-
- block->LabelLoop = AllocLabel();
- block->LabelBreak = AllocLabel();
-
- t = SkipToken(t, TokLParen);
- t = CompStmtDeclExp(t, &stmt->Stmt1, 0); /* exp */
- Assert(stmt->Stmt1->st_Tok == TokExp);
- /* don't deallocate result! */
- stmt->Stmt1->st_Func = (void (*)(void *))GenExpResult;
-
- t = SkipToken(t, TokRParen);
- t = SkipToken(t, TokLBrace);
-
- /*
- * now, each case and default is in its own block.
- */
-
- while (t && t != TokRBrace) {
- if (t == TokCase) {
- Exp *exp;
-
- if (siz == stmt->NumCases) {
- if (siz >= 32)
- siz *= 2;
- else
- siz += 4;
- stmt->Cases = zrealloc(stmt->Cases, sizeof(stmt->Cases[0]), stmt->NumCases, siz);
- stmt->Labels= zrealloc(stmt->Labels, sizeof(stmt->Labels[0]), stmt->NumCases, siz);
- stmt->CaseAry = zrealloc(stmt->CaseAry, sizeof(stmt->CaseAry[0]), stmt->NumCases, siz);
- }
-
- if (haveCase)
- BlockUp();
- stmt->CaseAry[stmt->NumCases] = BlockDown(BT_BLOCK);
- {
- long l = AllocLabel();
-
- stmt->CaseAry[stmt->NumCases]->LabelTest = l;
- stmt->Labels[stmt->NumCases] = l;
- }
- t = CompExp(GetToken(), &exp, 1);
- stmt->Cases[stmt->NumCases] = ExpToConstant(exp);
- ++stmt->NumCases;
- t = SkipToken(t, TokColon);
- haveCase = 1;
- } else if (t == TokDefault) {
- if (haveCase)
- BlockUp();
- if (stmt->DefBlock)
- zerror(EERROR_DUPLICATE_DEFAULT);
- stmt->DefBlock = BlockDown(BT_BLOCK);
- stmt->DefBlock->LabelTest = AllocLabel();
- stmt->DefCaseNo = stmt->NumCases; /* insert before... */
-
- t = SkipToken(GetToken(), TokColon);
- haveCase = 1;
- } else {
- Stmt *caseStmt;
-
- if (haveCase == 0 &&
- t != TokStruct &&
- t != TokEnum &&
- t != TokUnion &&
- t != TokTypeQual &&
- t != TokTypeDef &&
- t != TokTypeId &&
- t != TokTypeof)
- {
- stmt->BeforeBlock = BlockDown(BT_BLOCK);
- haveCase = 1;
- }
-
- t = CompStmtDeclExp(t, &caseStmt, 1);
-
- /* Handle the case where they put code before the first case statement */
- BlockAddStmt(caseStmt);
- }
- }
-
- if (haveCase)
- BlockUp();
-
- t = GetToken();
-
- BlockUp();
-
- return(t);
- }
-
- /*
- * break;
- */
-
- short
- CompBreak(short t, Stmt **pstmt)
- {
- BreakStmt *stmt = AllocTmpStructure(BreakStmt);
-
- t = SkipToken(t, TokSemi);
-
- *pstmt = (Stmt *)stmt;
- stmt->st_Func = (void (*)(void *))GenBreak;
- stmt->st_Tok = TokBreak;
- stmt->st_LexIdx = LFBase->lf_Index;
- if ((stmt->BreakLabel = FindBreakLabel()) == 0)
- zerror(EERROR_BREAK_OUTSIDE_LOOPSW);
- return(t);
- }
-
- short
- CompContinue(short t, Stmt **pstmt)
- {
- ContinueStmt *stmt = AllocTmpStructure(ContinueStmt);
-
- t = SkipToken(t, TokSemi);
-
- *pstmt = (Stmt *)stmt;
- stmt->st_Func = (void (*)(void *))GenContinue;
- stmt->st_Tok = TokContinue;
- stmt->st_LexIdx = LFBase->lf_Index;
- if ((stmt->ContLabel = FindContinueLabel()) == 0)
- zerror(EERROR_CONT_OUTSIDE_LOOP);
- return(t);
- }
-
- /*
- * goto label;
- */
-
- short
- CompGoto(short t, Stmt **pstmt)
- {
- GotoStmt *stmt = AllocTmpStructure(GotoStmt);
- SemInfo *sem = NULL;
-
- *pstmt = (Stmt *)stmt;
- stmt->st_Func = (void (*)(void *))GenGoto;
- stmt->st_Tok = TokGoto;
- stmt->st_LexIdx = LFBase->lf_Index;
-
- switch(t) {
- case TokId:
- case TokVarId:
- case TokEnumConst:
- if ((sem = FindSymbolId(LexSym, TokLabelId)) == NULL)
- {
- SemanticAddTopBlock(LexSym, TokLabelId, (void *)0);
- sem = FindSymbolId(LexSym, TokLabelId);
- }
- break;
- case TokLabelId:
- Assert(0);
- break;
- default:
- zerror(EERROR_SYNTAX_ERROR_EXP);
- break;
- }
- stmt->GotoLabel = sem;
- t = GetToken();
- t = SkipToken(t, TokSemi);
- return(t);
- }
-
- short
- CompLabel(short t, Stmt **pstmt)
- {
- LabelStmt *stmt = AllocTmpStructure(LabelStmt);
- SemInfo *sem;
- long label;
-
- *pstmt = (Stmt *)stmt;
- stmt->st_Func = (void (*)(void *))GenLabel;
- stmt->st_Tok = TokLabelId;
- stmt->st_LexIdx = LFBase->lf_Index;
-
- if ((sem = FindSymbolId(LexSym, TokLabelId)) == NULL) {
- label = AllocLabel();
- SemanticAddTopBlock(LexSym, TokLabelId, (void *)label);
- } else {
- /* How can this be... We have to issue an error message because */
- /* They have defined the label twice... */
- label = (long)sem->Data;
- if (label)
- {
- zerror(EWARN_DUPLICATE_SYMBOL, LexSym->Len, LexSym->Name);
- }
- else
- {
- label = AllocLabel();
- sem->Data = (void *)label;
- }
- }
- stmt->Label = label;
- t = SkipToken(GetToken(), TokColon);
-
- /*
- * normally label: is bundled with a statement. However, there are
- * a few special cases where this is not so.
- */
-
- if (t != TokRBrace && t != TokCase && t != TokDefault)
- t = CompStmtDeclExp(t, &stmt->Stmt1, 1);
- return(t);
- }
-
-
- /*
- * return exp;
- */
-
- short
- CompReturn(short t, Stmt **pstmt)
- {
- ReturnStmt *stmt = AllocTmpStructure(ReturnStmt);
-
- *pstmt = (Stmt *)stmt;
- stmt->st_Func = (void (*)(void *))GenReturn;
- stmt->st_Tok = TokReturn;
- stmt->st_LexIdx = LFBase->lf_Index;
-
- if (t != TokSemi) {
- t = CompStmtDeclExp(t, &stmt->Stmt1, 0); /* exp */
- if (stmt->Stmt1->st_Tok != TokExp)
- zerror(EFATAL_SYNTAX_ERROR_EXP);
- /* save result */
- stmt->Stmt1->st_Func = (void (*)(void *))GenExpResult;
- }
- t = SkipToken(t, TokSemi);
-
- return(t);
- }
-
- /*
- * __breakpoint
- */
-
- short
- CompBreakPoint(short t, Stmt **pstmt)
- {
- BreakPointStmt *stmt = AllocTmpStructure(BreakPointStmt);
-
- *pstmt = (Stmt *)stmt;
- stmt->st_Func = (void (*)(void *))GenBreakPoint;
- stmt->st_Tok = TokBreakPoint;
- stmt->st_LexIdx = LFBase->lf_Index;
-
- return(t);
- }
-
-
-